package edu.ncut.vod.taglib;

import java.io.IOException;
import java.util.List;
import java.util.Vector;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspWriter;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.web.servlet.tags.RequestContextAwareTag;

import edu.ncut.vod.taglib.VideoInformationTag;
import edu.ncut.vod.taglib.Pageable;

import edu.ncut.vod.hibernate.model.VideoInfo;
import edu.ncut.vod.hibernate.service.VideoInformationService;

/**
 * public abstract class RequestContextAwareTag extends TagSupport implements TryCatchFinally:
 * Superclass for all tags that require a RequestContext. The RequestContext instance provides 
 * easy access to current state like WebApplicationContext, Locale, Theme, etc. 
 */
public class VideoInformationTag extends RequestContextAwareTag implements BeanPostProcessor {

    private static final long serialVersionUID = -5728133330472190184L;
    int page;// when paging,it indicates which page to go to
    int totalPages = 0;// totalPages indicates the number of total pages
    int count;//count indicates the amount of rows of result of search
    int currentPage = 1;//current indicates the number of current page
    List lists;//it stores all object 'videoinfo'
    Vector vector;//it contains all rows of current page
    /**
     * 'pageContext' is a field in object 'TagSupport',whose method
     * 'getOut()' returns a object 'JspWriter'
     */
    JspWriter out;
    
    /*
     * an attribute from service layer which provides service about video information and depends
     * on injection from Spring container. 
     */
    VideoInformationService videoInformationService;    

    public void setVideoInformationService(
            VideoInformationService videoInformationService) {
        this.videoInformationService = videoInformationService;
    }
    
    public VideoInformationService getVideoInformationService() {
        return videoInformationService;
    }

    /*
     * when extending class RequestContestAwareTag,method 'doStartTagInternal' must be implemented
     * @see org.springframework.web.servlet.tags.RequestContextAwareTag#doStartTagInternal()
     */
    @Override
    public int doStartTagInternal() throws Exception {        

        /*ApplicationContext ctx = new ClassPathXmlApplicationContext("/WEB-INF/applicationContext.xml");
        VideoInformationTag videoInformationTag = (VideoInformationTag) ctx.getBean("videoInformationTag");
        System.out.println(videoInformationTag);*/      
        
        setPage();
        //debug("setPage");
        setTotalPage();
        //debug("setTotalPage");
        setCurrentPage();
        //debug("setCurrentPage");
                
        // 获得所有的videoinfo对象,并将它们保存到List对象中去
        lists = videoInformationService.getVideoinfos();

        vector = addRows(lists, page);
        showTable(vector);
        
        return EVAL_PAGE;
    }
    
    /**
     * set attribute 'currentPage'
     */
    public void setCurrentPage(){
        if (page == -1) {// it may be the first page
            currentPage = 1;
        } else if (page == -4) {// it may be the last page
            currentPage = totalPages;
        } else if(page == -2){
            currentPage = currentPage - 1;
        }else if(page == -3){
            currentPage = currentPage + 1;
        }else{
            currentPage = 1;
        }
        //debug("currentPage : " + currentPage);
    }
    
    /**
     * set attribute 'totalPage'
     */
    public void setTotalPage(){
        /**
         * protected final RequestContext getRequestContext():Return the current RequestContext.
         * 
         * public class RequestContext extends Object: Context holder for request-specific state, 
         * like current web application context, current locale, current theme, 
         * and potential binding errors. Provides easy access to localized messages 
         * and Errors instances. 
         * 
         * public final WebApplicationContext getWebApplicationContext():
         * Return the current WebApplicationContext. 
         * 
         * public interface WebApplicationContext extends ApplicationContext, ThemeSource:
         * Interface to provide configuration for a web application.
         * 
         * Object getBean(String name) throws BeansException:
         * Return an instance, which may be shared or independent, of the given bean name. 
         * This method allows a Spring bean factory to be used as a replacement for 
         * the Singleton or Prototype design pattern. 
         */
        //if not this sentence,an exception will occurs in console:java.lang.NullPointerException
        videoInformationService = (VideoInformationService) this.getRequestContext().getWebApplicationContext().getBean("videoInformationService"); 
                
        // count indicates the amount of rows of result of search
        count = videoInformationService.getResultSize();
        //debug("count:" + count);
        
        if (count % 5 == 0) {
            totalPages = count / 5;
        } else {
            totalPages = count / 5 + 1;
        }
        //debug("totalPages : " + totalPages);
    }
    
    /**
     * set attribute 'page'
     */
    public void setPage(){
        /**
         * method 'getRequest()' of field(object) 'pageContext' returns a object
         * 'ServletRequest',so it need be converted to class
         * 'HttpServletRequest'
         */
        HttpServletRequest request = (HttpServletRequest) pageContext
                .getRequest();

        /**
         * method 'getQueryString()' of object 'request' returns the query
         * string that is contained in the request URL after the path
         */
        String str = (String) request.getQueryString();
        //debug("QueryString : " + str);
        
        if (str == null || str.equals("")) {
            page = 1;
            //debug("page = 1");
        } else {
            String[] aa = str.split("=");// according to '=',parse parameter
            //judge whether parameter in URL is a minus quantity
            Pattern pattern = Pattern.compile("^((-\\d+)|(0+))$"); 
            //debug("aa[1]:"+aa[1]);
            if(pattern.matcher(aa[1]).matches()){
                page = Integer.parseInt(aa[1]);// get the number of page                
            }else{
                page = 1;// get the number of page
            }
        }
        //debug("page : " + page);
    }

    /**
     * search all content of this page,and add them into object 'Vector' as
     * return value
     * @param lists
     * @param page
     * @return:object 'Vector',including all content of this page
     */
    public Vector addRows(List lists, int page) {
        try {
            // 创建Vector对象,用来保存当前页的5行数据
            Vector vector = new Vector();
            // 创建Pageable对象
            Pageable pgb = new Pageable(lists);
            // 设置每一页的行数
            pgb.setPageSize(5);
            // 转到第page页
            pgb.gotoPage(page);
            // 获得当前页第rowsCount-1行的数据,并将其赋给Videoinfo对象
            VideoInfo vi = (VideoInfo) lists.get(pgb.getRowsCount() - 1);

            int i = 0;
            if (vi != null) {
                while (vi != null && i < pgb.getCurrentPageRowsCount()) {                    
                    vi = (VideoInfo) lists.get(pgb.getRowsCount() + i - 1);
                    if (pgb != null && pgb.getCurrentPageRowsCount() != 0) {

                        // 获得当前行的各个字段
                        Integer videoId = vi.getVideoid();
                        String informationName = vi.getInformationname();
                        String informationDescription = vi.getInformationdescription();
                        String secondLevelColumnId = vi.getSecondlevelcolumnid();
                        String firstLevelColumnId = vi.getFirstlevelcolumnid();
                        String fileSize = vi.getFilesize();
                        Integer browseNumber = vi.getBrowsenumber();
                        // 将各个字段保存到Vector对象中去
                        vector.add(new VideoInfo(videoId,informationName,
                                informationDescription, secondLevelColumnId,
                                firstLevelColumnId, fileSize, browseNumber));                        
                    }
                    i++;                    
                }
            }
            return vector;
        } finally {

        }
    }

    /**
     * 
     * @param vector
     */
    public void showTable(Vector vector){
        out = pageContext.getOut();
        
        try {
            out.println("<table width=\"90%\"  border=\"0\" cellspacing=\"1\" cellpadding=\"1\" class=\"tableBorder\">");
            out.println("<caption align=\"center\" background=\"../images/videoinformationtag_bg_1.gif\" class=\"whitenormal\">视频文件信息</caption>");

            out.println("<tr>");
            out.println("<th width=\"10%\" bgcolor=\"E4EDF9\" class=\"normalText\">编号</th>");
            out.println("<th width=\"20%\" bgcolor=\"E4EDF9\" class=\"normalText\">名称</th>");
            out.println("<th width=\"30%\" bgcolor=\"E4EDF9\" class=\"normalText\">描述</th>");
            out.println("<th width=\"10%\" bgcolor=\"E4EDF9\" class=\"normalText\">二级目录id</th>");
            out.println("<th width=\"10%\" bgcolor=\"E4EDF9\" class=\"normalText\">一级目录id</th>");
            out.println("<th width=\"10%\" bgcolor=\"E4EDF9\" class=\"normalText\">文件大小</th>");
            out.println("<th width=\"10%\" bgcolor=\"E4EDF9\" class=\"normalText\">浏览次数</th>");
            out.println("</tr>");

            for (int i = 1; i < vector.size() + 1; i++) {
                VideoInfo vi = (VideoInfo) vector.get(i - 1);

                out.println("<tr>");

                out.println("<td width=\"10%\" align=\"center\" bgcolor=\"E4EDF9\" class=\"normalText\">"
                                + i + "</td>");

                out.println("<td width=\"20%\" align=\"center\" bgcolor=\"E4EDF9\"><a href=\"/VideoOnDemand_v7/videoManager.do?videoid="
                                + ((VideoInfo) vector.get(i - 1)).getVideoid()
                                + "\">"
                                + ((VideoInfo) vector.get(i - 1)).getInformationname() + "</a></td>");

                out.println("<td width=\"30%\" align=\"center\" bgcolor=\"E4EDF9\" class=\"normalText\">"
                                + ((VideoInfo) vector.get(i - 1)).getInformationdescription() + "</td>");

                out.println("<td width=\"10%\" align=\"center\" bgcolor=\"E4EDF9\" class=\"normalText\">"
                                + ((VideoInfo) vector.get(i - 1)).getSecondlevelcolumnid() + "</td>");

                out.println("<td width=\"10%\" align=\"center\" bgcolor=\"E4EDF9\" class=\"normalText\">"
                                + ((VideoInfo) vector.get(i - 1)).getFirstlevelcolumnid() + "</td>");

                out.println("<td width=\"10%\" align=\"center\" bgcolor=\"E4EDF9\" class=\"normalText\">"
                                + ((VideoInfo) vector.get(i - 1)).getFilesize()
                                + "</td>");

                out.println("<td width=\"10%\" align=\"center\" bgcolor=\"E4EDF9\" class=\"normalText\">"
                                + ((VideoInfo) vector.get(i - 1)).getBrowsenumber() + "</td>");

                out.println("</tr>");

            }

            out.println("<tr>");

            out.println("<td colspan=\"7\"><table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" bgcolor=\"E4EDF9\">");

            out.println("<tr class=\"normalText\">");

            out.println("<td>页次:" + currentPage + "/" + totalPages
                    + "页&nbsp;&nbsp;&nbsp;每页5行 &nbsp;&nbsp;&nbsp;总共" + count
                    + "行</td>");

            out.println("<td align=\"right\">分页:");
            if (page == 1 || currentPage == 1) {
                
            }else{
                out.println("<a href=\"index.jsp?arg1=-1\">首页</a> "); 
            }
            if (page == 1 || currentPage == 1) {
                
            }else{
                out.println("<a href=\"index.jsp?arg2=-2\">上一页</a> ");
            }
            if (currentPage == totalPages) {
                
            }else{
                out.println("<a href=\"index.jsp?arg3=-3\">下一页</a> ");
            }
            if (currentPage == totalPages || page == -4) {
                
            }else{
                out.println("<a href=\"index.jsp?arg4=-4\">尾页</a></td>");
            }

            out.println("</tr>");

            out.println("</table></td>");

            out.println("</tr>");

            out.println("</table>");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * print mesage in console
     * @param message
     */
    public static void debug(String message) {
        System.out.println(message);
    }

    /**
     * this method is called on the bean just before this bean is removed from the container
     */
    public void destroy() {
        debug("destroy mothed in VideoInformationTag object is called");
    }

    /**
     * this method is called on the bean immediately upon instantiation
     */
    public void setup() {
        debug("setup mothed in VideoInformationTag object is called");
    }

    /*
     * the postProcessAfterInitialization() method is called immediately after initialization.
     * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String)
     */
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        debug("postProcessAfterInitialization mothed in VideoInformationTag object is called");
        return null;
    }

    /*
     * The postProcessBeforeInitialization() method is called immediately prior to bean 
     * initialization (the call to afterPropertiesSet() and the bean’s custom initmethod).
     * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
     */
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        debug("postProcessBeforeInitialization mothed in VideoInformationTag object is called");
        return null;
    }
}
